home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / CRS / crs08.d81 / unzip.c < prev    next >
Text File  |  2009-10-10  |  12KB  |  453 lines

  1.  
  2. #include    "stdio.h"
  3. #include    "unzip.h"
  4.  
  5. struct zhdr {
  6.     long            signature;
  7.     int             version_needed;
  8.     int             gp_flag;
  9.     int             method;
  10.     int             time;
  11.     int             date;
  12.     long            crc32;
  13.     long            comp_size;
  14.     long            file_size;
  15.     int             fn_len;
  16.     int             extra_len;
  17. }               zhdr;
  18.  
  19. long            tot_comp_size,
  20.                 tot_file_size;
  21. int             num_of_files;
  22.  
  23. char           *buffer;                /* change to dynamic allocation */
  24. char           *bufpt;                /* indexes thru above */
  25.  
  26. char            out_fname[80];
  27. char            file_spec[80];
  28.  
  29. long            bytes_in,
  30.                 bytes_out;
  31.  
  32. unsigned int    bits_left,
  33.                 s_r;
  34. int             zipeof;
  35. int             extr_flag;
  36.  
  37. unsigned int    buf_size;
  38. unsigned int    scrn_upd_cnt;
  39.  
  40. FILE           *infd;
  41. FILE           *outfd;
  42.  
  43. char            months[12][4] = {
  44.                  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  45.                  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  46.  
  47. char            method_name[7][7] = {
  48.                      "Stored", "Shrunk", "Reduc1", "Reduc2", "Reduc3", "Reduc4", "Implod"};
  49. /* ========================================================================= */
  50.  
  51. void
  52. fatal_exit(message)
  53.     char           *message;
  54. {
  55.     printf(message);
  56.     exit();
  57. }
  58.  
  59. void
  60. inibuf()
  61. {
  62.     int             i;
  63.     for (i = 0; i < buf_size; i++)
  64.     buffer[i] = 0;                /* init the buffer */
  65. }
  66.  
  67. int
  68. status(fn)
  69.     char           *fn;
  70. {
  71.  
  72. #ifdef  MSC
  73.  
  74.     if (access(fn, 0) == 0)
  75.     return (EXISTS);
  76.     else
  77.     return (DOES_NOT_EXIST);
  78. #else
  79.  
  80.     /* do it without the benefit of the 'access' function... */
  81.  
  82.     FILE           *temp_id;
  83.     if ((temp_id = fopen(fn, READ_ACCESS)) == NULL)
  84.     return (DOES_NOT_EXIST);
  85.     else {
  86.     fclose(temp_id);
  87.     return (EXISTS);
  88.     }
  89.  
  90. #endif
  91. }
  92.  
  93. int
  94. open_out()
  95. {
  96.     unsigned char   answ;
  97.     if (status(out_fname) == EXISTS) {
  98.     printf("  Overwrite existing file?\007 ");
  99.     while (((answ = (toupper(getc(stdin)))) != 'Y') && (answ != 'N'));
  100.     if (answ != 'Y') {
  101.         printf("\n");
  102.         return (FAILURE);
  103.     }
  104.     }
  105.     if ((outfd = fopen(out_fname, WRITE_ACCESS)) == NULL) {
  106.     printf("\n** Error, cannot open file %s", out_fname);
  107.     return (FAILURE);
  108.     } else
  109.     return (SUCCESS);
  110. }
  111.  
  112. int
  113. next_bit()
  114. {
  115.     int             bit;
  116.     if (bits_left-- == 0) {
  117.     if ((s_r = getc(infd)) == EOF)
  118.         fatal_exit("\nUnexpected EOF\n");
  119.     bits_left = 7;
  120.     if (++bytes_in >= zhdr.comp_size)
  121.         zipeof = -1;
  122.     }
  123.     bit = s_r & 0x0001;
  124.     s_r = (s_r >> 1);
  125.     return (bit);
  126. }
  127.  
  128. void
  129. update_screen()
  130. {
  131.     printf("\015%dk", (unsigned int) (bytes_out / 1024L));
  132. }
  133.  
  134. void
  135. put_ch(ch)
  136.     char            ch;
  137. {
  138.     if (buf_size) {
  139.     *bufpt++ = ch;
  140.     if ((unsigned int) bufpt - (unsigned int) buffer >= buf_size)
  141.         bufpt = buffer;
  142.     }
  143.     putc(ch, outfd);
  144.     bytes_out++;
  145.     if (scrn_upd_cnt++ > 1023) {
  146.     scrn_upd_cnt -= 1024;
  147.     update_screen();
  148.     }
  149. }
  150.  
  151. int
  152. get_num(nbits)
  153.     int             nbits;
  154. {
  155.     unsigned int    tot,
  156.                     i;
  157.     tot = 0;
  158.  
  159.     for (i = 0; i < nbits; i++) {
  160.     tot = tot >> 1;
  161.     if (next_bit() != 0)
  162.         tot |= 0x8000;
  163.     }
  164.     return (tot >> (16 - nbits));
  165. }
  166.  
  167. int
  168. proc_header()
  169. {
  170.     /* Read in the whole local header structure (starts with 'signature') */
  171.  
  172.     fread(&zhdr.signature, 1, sizeof(zhdr), infd);
  173.  
  174.     if (zhdr.signature == CENTRAL_SIGNATURE)
  175.         return (END_OF_ZIP);
  176.  
  177.     if (zhdr.signature != LOCAL_SIGNATURE)
  178.         fatal_exit("\nInvalid ZIP file format.");
  179.  
  180.     if (zhdr.version_needed > THIS_VERSION)
  181.         fatal_exit("\nNeed newer version of this program.");
  182.  
  183.     fread(out_fname, 1, zhdr.fn_len, infd);
  184.     out_fname[zhdr.fn_len] = 0;            /* make it a 'real' string */
  185.  
  186.     if (STRCHR(out_fname, '.') == 0)        /* guarantee it has a '.' */
  187.         strcat(out_fname, ".");
  188.  
  189.     fseek(infd, (long) zhdr.extra_len, CURRENT);/* skip the extra field */
  190.  
  191.     return (SUCCESS);
  192. }
  193. /* ========================================================================= */
  194.  
  195. void
  196. unstore()
  197. {                        /* extract a file which is STORED */
  198.     buf_size = 0;
  199.     bits_left = 0;                /* not really necessary */
  200.     s_r = 0;                    /* likewise */
  201.  
  202.     printf("\n");
  203.  
  204.     while (bytes_out < zhdr.file_size)
  205.     put_ch(getc(infd));
  206.  
  207.     free(buffer);
  208. }
  209. /* ========================================================================= */
  210. /*
  211.  * match() compares a pattern with a string.  Wildcards accepted in the pattern are:  "*" for zero or more arbitrary
  212.  * characters;  "?" for any one characters.  Unlike the MS-DOS wildcard match, "*" is correctly handled even if it
  213.  * isn't at the end of the pattern. ".' is not special. 
  214.  *
  215.  * Originally written by Jeff Damens of Columbia University Center for Computing Activities.  Taken from the source code
  216.  * for C-Kermit version 4C. 
  217.  */
  218. /*
  219.  * Note: I left this routine intact, but did add a "." character to either a filename or match pattern that originally
  220.  * had a blank extension (done elsewhere, before this routine is called). This provides a minimum expected
  221.  * compatibility with MS-DOS conventions, eg that "*.*" refers to all files, not all files except those with blank
  222.  * extensions. - SGG 
  223.  */
  224.  
  225. int
  226. match(string, pattern)
  227.     char           *string,
  228.                    *pattern;
  229. {
  230.     char           *psave,
  231.                    *ssave;            /* back up pointers for failure */
  232.     psave = ssave = ((char *) 0);
  233.     while (1) {
  234.     for (; *pattern == *string; pattern++, string++)    /* skip first */
  235.         if (*string == '\0')
  236.         return (1);            /* end of strings, succeed */
  237.     if (*string != '\0' && *pattern == '?') {
  238.         pattern++;                /* '?', let it match */
  239.         string++;
  240.     } else if (*pattern == '*') {        /* '*' ... */
  241.         psave = ++pattern;            /* remember where we saw it */
  242.         ssave = string;            /* let it match 0 chars */
  243.     } else if (ssave != ((char *) 0) && *ssave != '\0') {    /* if not at end  */
  244.         /* ...have seen a star */
  245.         string = ++ssave;            /* skip 1 char from string */
  246.         pattern = psave;            /* and back up pattern */
  247.     } else
  248.         return (0);                /* otherwise just fail */
  249.     }
  250. }
  251.  
  252. void 
  253. type_out_fname()
  254. {                        /* type output file name AND it's size */
  255.     printf(" %12s (%3dk)", out_fname, (zhdr.file_size + 1023) / 1024);
  256. }
  257.  
  258. /* ======================================================================== */
  259. void
  260. extract1()
  261. {
  262.     if (STRCHR(out_fname, '.') == NULL)
  263.     strcat(out_fname, ".");
  264.  
  265.     if (!(match(out_fname, file_spec))) {    /* does it match spec'd filespec ? */
  266.     printf("\015** Skipping: ");
  267.     type_out_fname();
  268.     printf("\n");
  269.     fseek(infd, zhdr.comp_size, CURRENT);    /* skip the member */
  270.     return;
  271.     }
  272.     bytes_out = 0L;
  273.     bytes_in = 0L;
  274.     zipeof = 0;
  275.     scrn_upd_cnt = 1024;
  276.  
  277.     switch (zhdr.method) {
  278.  
  279.     case STORED:
  280.     printf("\015Extracting:  ");
  281.     type_out_fname();
  282.     if (open_out() == FAILURE) {
  283.         fseek(infd, zhdr.comp_size, CURRENT);    /* skip the member */
  284.         return;
  285.     }
  286.     unstore();
  287.     break;
  288.  
  289.     case SHRUNK:
  290.     printf("\015Stretching:  ");
  291.     type_out_fname();
  292.     if (open_out() == FAILURE) {
  293.         fseek(infd, zhdr.comp_size, CURRENT);    /* skip the member */
  294.         return;
  295.     }
  296.     ovloader("unshrink");
  297.     break;
  298.  
  299.     case IMPLODED:
  300.     printf("\015Exploding:   ");
  301.     type_out_fname();
  302.     if (open_out() == FAILURE) {
  303.         fseek(infd, zhdr.comp_size, CURRENT);    /* skip the member */
  304.         return;
  305.     }
  306.     ovloader("explode");
  307.     break;
  308.  
  309.     case REDUCE_1:
  310.     case REDUCE_2:
  311.     case REDUCE_3:
  312.     case REDUCE_4:
  313.     printf("\015Oxidizing:   ");
  314.     type_out_fname();
  315.     if (open_out() == FAILURE) {
  316.         fseek(infd, zhdr.comp_size, CURRENT);    /* skip the member */
  317.         return;
  318.     }
  319.     ovloader("unreduce");
  320.     break;
  321.  
  322.     default:
  323.     printf("\015** Skipping:");
  324.     type_out_fname();
  325.     printf("  (Unknown compression method)\n");
  326.     fseek(infd, zhdr.comp_size, CURRENT);    /* skip the member */
  327.     return;
  328.     }
  329.  
  330.     fclose(outfd);
  331.     return;
  332. }
  333. /* ========================================================================= */
  334.  
  335. /* list a member file */
  336. void
  337. list1()
  338. {
  339.     int             yr,
  340.                     mo,
  341.                     dy;
  342.     int             hh,
  343.                     mm;
  344.     int             s_f;
  345.     int             kbytes;
  346.  
  347.     char            f_n[13],
  348.                     f_ext[4];
  349.     char           *dotpos;
  350.     yr = (zhdr.date >> 9) & 0x7f;        /* extract date from bit mapped fields */
  351.     mo = (zhdr.date >> 5) & 0x0f;
  352.     dy = zhdr.date & 0x1f;
  353.  
  354.     hh = (zhdr.time >> 11) & 0x1f;        /* likewise the time */
  355.     mm = (zhdr.time >> 5) & 0x3f;
  356.  
  357.     s_f = (int) (100L - ((100L * zhdr.comp_size) / zhdr.file_size));
  358.     kbytes = (int) ((zhdr.file_size + 1023L) / 1024L);
  359.  
  360.     tot_comp_size += zhdr.comp_size;
  361.     tot_file_size += zhdr.file_size;
  362.     num_of_files++;
  363.  
  364.     strncpy(f_n, out_fname, 13);        /* should copy the null, too */
  365.     dotpos = STRCHR(f_n, '.');
  366.     if (dotpos == NULL)
  367.     strcpy(f_ext, "   ");
  368.     else {
  369.     *dotpos = 0;
  370.     strncpy(f_ext, dotpos + 1, 4);        /* should copy the null, too */
  371.     }
  372.  
  373.     printf("%-8s.%3s  %7ld %4dk  %6s  %7ld %3d%%  %2d %3s %2d %2d:%02d  %08lx\n",
  374.        f_n, f_ext, zhdr.file_size, kbytes, &method_name[zhdr.method][0],
  375.        zhdr.comp_size, s_f, dy, &months[mo - 1][0], (yr + 80) % 100, hh, mm, zhdr.crc32);
  376.  
  377.     fseek(infd, zhdr.comp_size, CURRENT);    /* skip the member */
  378. }
  379. /* ========================================================================= */
  380.  
  381. void
  382. main(argc, argv)
  383.     int             argc;
  384.     unsigned char  *argv[];
  385. {
  386.     unsigned char   zip_file_name[80];
  387.     int             tot_disk_size,
  388.                     tot_s_f;
  389.     int                byte_1, byte_2;
  390.     int                exe_sz_mod_512, exe_sz_x_512;
  391.  
  392.     if ((argc < 2) || (argc > 3)) {
  393.     printf("\nUNZIP v0.99  Copyright 1989 S. Greenberg\n");
  394.     printf("    may be reproduced for non-profit use.\n");
  395.     printf("\nUsage: UNZIP  <filename[.zip]>  [<afn>]\n");
  396.     printf("\nExtracts all members matching <afn> from the specified ZIPfile.");
  397.     printf("\n  If <afn> is not present, a directory of the members will be displayed.\n");
  398.     exit();
  399.     }
  400.     printf("\nUNZIP  v0.99   SGG   09/11/89\n");
  401.  
  402.     strcpy(zip_file_name, argv[1]);
  403.     if (STRCHR(zip_file_name, '.') == 0)
  404.     strcat(zip_file_name, ".ZIP");
  405.  
  406.     if ((infd = fopen(zip_file_name, READ_ACCESS)) == NULL) {
  407.     printf("\nCan't open input file: %s", zip_file_name);
  408.     exit();
  409.     }
  410.     printf("\n ZIPfile = %s\n\n", zip_file_name);
  411.  
  412.     if (argc == 2) {
  413.     strcpy(file_spec, "*.*");        /* not spec'd means all files */
  414.     extr_flag = 0;
  415.     printf("Name           Length  Disk  Method   Stored Saved   Date    Time     CRC\n");
  416.     printf("============  =======  ====  ======  ======= ===== ========= =====  ========\n");
  417.     tot_comp_size = 0L;
  418.     tot_file_size = 0L;
  419.     num_of_files = 0;
  420.  
  421.     } else {
  422.     strcpy(file_spec, argv[2]);        /* filespec for extraction */
  423.     if (STRCHR(file_spec, '.') == 0)
  424.         strcat(file_spec, ".");
  425.     extr_flag = -1;
  426.     }
  427.  
  428.     if ((byte_1 = getc(infd)) == EOF)
  429.         fatal_exit("\nFile is empty.");
  430.  
  431.     if ((byte_1 == 'M') && ((byte_2 = getc(infd)) == 'Z')) {
  432.         fread(&exe_sz_mod_512, 1, 2, infd);    /* skip EXE section of SXF types */
  433.         fread(&exe_sz_x_512, 1, 2, infd);
  434.         fseek(infd, (long) (exe_sz_x512 * 512 + exe_sz_mod_512 -512 -6), CURRENT);
  435.     } else
  436.         fseek(infd, 0L, BEGINNING);    /* regular zip, rewind to beginning */
  437.  
  438.     while (proc_header() != END_OF_ZIP) {
  439.     if (extr_flag)
  440.         extract1();
  441.     else
  442.         list1();
  443.     }
  444.     if (!extr_flag) {
  445.     tot_disk_size = (int) ((tot_file_size + 1023L) / 1024L);
  446.     tot_s_f = (int) (100L - ((100L * tot_comp_size) / tot_file_size));
  447.     printf("============  =======  ====          ======= =====\n");
  448.     printf("Total    %3d  %7ld %4dk          %7ld %3d%%\n",
  449.            num_of_files, tot_file_size, tot_disk_size, tot_comp_size, tot_s_f);
  450.     }
  451.     fclose(infd);
  452. }
  453.